package com.csap.framework.validation.factory;

import com.csap.framework.extension.FilterClassParam;
import com.csap.framework.util.CollectionsUtil;
import com.csap.framework.util.map.CsapMap;
import com.csap.mybatisplus.core.toolkit.StringPool;
import lombok.extern.slf4j.Slf4j;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yangchengfu
 * @description 数据验证工厂类型
 * @dataTime 2021年-01月-22日 17:46:00
 **/
@Slf4j
public abstract class BaseFactory implements ValidateFilter {
    /**
     * 验证缓存对象
     * <p>
     * key is className  add methodName
     * value is method validate info
     * <p/>
     */
    protected Map<String, Validate> validateMap = new ConcurrentHashMap<>();

    /**
     * 方法获取验证参数
     *
     * @param controller class类
     * @param method     方法
     * @return
     */
    public Validate method(Class<?> controller, Method method) {
        return method(controller.getName() + StringPool.DOT + method.getName());
    }

    /**
     * 方法获取验证参数
     *
     * @param controller class类
     * @param method     方法
     * @return
     */
    public Validate method(String controller, String method) {
        return method(controller + StringPool.DOT + method);
    }

    /**
     * 方法获取验证参数
     * <p>controllerName+methodName<p/>
     *
     * @param classNameAndMethodName 键
     * @return
     */
    public Validate method(String classNameAndMethodName) {
        return validateMap.computeIfAbsent(classNameAndMethodName, k -> new Validate());
    }

    /**
     * 方法获取验证参数
     *
     * @param controller class类
     * @param method     方法
     * @param field      键名称
     * @return 返回当前字段需要验证的列表
     */
    public Validate.ValidateField request(Class<?> controller, Method method, String field) {
        return method(controller, method).field(field);
    }

    /**
     * 方法获取验证参数-直接获取目标参数
     *
     * @param controller    class类
     * @param method        方法
     * @param field         键名称
     * @param parameterName 参数名称
     * @return 返回当前字段需要验证的列表
     */
    public Validate.ValidateField request(Class<?> controller, Method method, String field, String parameterName) {
        return method(controller, method).field(field).getChildren().get(parameterName);
    }

    /**
     * 添加请求验证参数
     *
     * @param key      键名称
     * @param fieldKey 字段名称
     * @return 返回当前字段需要验证的列表
     */
    public Validate.ValidateField addRequest(String key, String fieldKey, List<Validate.ConstraintValidatorField> list) {
        return method(key).addValidateField(fieldKey, list);
    }

    /**
     * 方法获取验证参数
     *
     * @param controller class类
     * @param method     方法
     * @return 返回过滤对象
     */
    public List<FilterClassParam> response(Class<?> controller, Method method) {
        return method(controller, method).getFilterClassParams();
    }

    /**
     * 方法获取验证参数
     *
     * @param classNameAndMethodName 键名称
     * @param modelClass             参数对象
     * @return 返回过滤对象
     */
    public FilterClassParam addResponse(String classNameAndMethodName, Class<?> modelClass) {
        return method(classNameAndMethodName).filterResponse(modelClass);
    }

    /**
     * 添加返回参数
     *
     * @param classNameAndMethodName 键名称
     * @param field                  字段
     */
    public FilterClassParam addIncluds(String classNameAndMethodName, String field, Class<?> modelClass) {
        return addResponse(classNameAndMethodName, modelClass).addIncluds(field);
    }

    /**
     * 添加返回参数
     *
     * @param classNameAndMethodName 键名称
     * @param field                  字段
     */
    public FilterClassParam addExcludes(String classNameAndMethodName, String field, Class<?> modelClass) {
        return addResponse(classNameAndMethodName, modelClass).addExcludes(field);
    }

    /**
     * 添加请求参数验证
     *
     * @param key         键
     * @param fileKeyName 字段
     */
    public Validate.ValidateField addRequestValidate(String key, String fileKeyName, Annotation[] annotations, String fieldName, BaseModel baseModel) {
        //TODO 获取当前字段验证规则集合
        List<Validate.ConstraintValidatorField> list = getAllFieldConstraintValidator(baseModel.getField(), annotations);
        if (CollectionsUtil.isEmpty(list)) {
            return null;
        }
        return baseModel.getValidateField() != null ?
                addValidateField(fieldName, baseModel.getValidateField(), list) :
                method(key)
                        .addValidateField(fileKeyName, baseModel)
                        .addValidateField(fieldName, list, baseModel);

    }

    /**
     * 添加验证的字段
     *
     * @param fieldKey             字段标识
     * @param constraintValidators 验证逻辑
     * @return
     */
    public Validate.ValidateField addValidateField(String fieldKey, CsapMap<String, Validate.ValidateField> validateField, List<Validate.ConstraintValidatorField> constraintValidators) {
        return validateField.computeIfAbsent(fieldKey, k -> new Validate.ValidateField().constraintValidators(constraintValidators));
    }


}
